home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / m2posx10.zoo / m2posix.10 / src / sig.ipp < prev    next >
Encoding:
Modula Implementation  |  1993-12-23  |  13.1 KB  |  542 lines

  1. IMPLEMENTATION MODULE sig;
  2. __IMP_SWITCHES__
  3. #ifdef HM2
  4. #ifdef __LONG_WHOLE__
  5. (*$!i+: Modul muss mit $i- uebersetzt werden! *)
  6. (*$!w+: Modul muss mit $w- uebersetzt werden! *)
  7. #else
  8. (*$!i-: Modul muss mit $i+ uebersetzt werden! *)
  9. (*$!w-: Modul muss mit $w+ uebersetzt werden! *)
  10. #endif
  11. #endif
  12. (*****************************************************************************)
  13. (* Basiert auf der MiNTLIB von Eric R. Smith und anderen                     *)
  14. (* --------------------------------------------------------------------------*)
  15. (* 30-Okt-93, Holger Kleinschmidt                                            *)
  16. (*****************************************************************************)
  17.  
  18. VAL_INTRINSIC
  19. CAST_IMPORT
  20.  
  21. FROM PORTAB IMPORT
  22. (* CONST*) NULL,
  23. (* TYPE *) UNSIGNEDWORD, SIGNEDLONG, UNSIGNEDLONG, WORDSETRANGE, WORDSET;
  24.  
  25. FROM types IMPORT
  26. (* TYPE *) pidT;
  27.  
  28. IMPORT e;
  29.  
  30. FROM DosSystem IMPORT
  31. (* VAR  *) BASEP,
  32. (* PROC *) SysClock, DosPid, MiNTVersion;
  33.  
  34. FROM OSCALLS IMPORT
  35. (* PROC *) Pkill, Psigpause, Psigblock, Psigsetmask, Psigpending, Pause,
  36.            Pterm, Talarm, Fselect;
  37.  
  38. (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
  39.  
  40. CONST
  41.   EOKL = 0H;
  42. #if no_MIN_MAX
  43.   MINSIG = SIGNULL;
  44.   MAXSIG = SIGUSR2;
  45. #else
  46.   MINSIG = MIN(Signal);
  47.   MAXSIG = MAX(Signal);
  48. #endif
  49.  
  50. TYPE
  51.   SigDispatcher = PROCEDURE(UNSIGNEDWORD);
  52.  
  53. TYPE
  54.   MiNTSigset = RECORD
  55.     CASE TAG_COLON BOOLEAN OF
  56.       FALSE: sigset  : sigsetT;
  57.      |TRUE : siglong : UNSIGNEDLONG;
  58.     END;
  59.   END;
  60.  
  61. VAR
  62.   MiNT       : BOOLEAN;
  63.   SIGMASK    : MiNTSigset;
  64.   SIGPENDING : MiNTSigset;
  65.  
  66. VAR
  67. #if only_subrange_index
  68.   Handler : ARRAY [MINSIG..MAXSIG] OF SignalHandler;
  69. #else
  70.   Handler : ARRAY Signal OF SignalHandler;
  71. #endif
  72.  
  73. #if 0
  74. VAR
  75.   Wrapper : RECORD
  76.     code1 : ARRAY [0..2] OF UNSIGNEDLONG;
  77.     call  : SigDispatcher;
  78.     code2 : UNSIGNEDLONG;
  79.   END;
  80. #endif
  81.  
  82. (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
  83.  
  84. (* allgemeine Mengenprozeduren, fuer Signalsets beliebiger Groesse *)
  85.  
  86. PROCEDURE SigsetIsEmpty ((* EIN/ -- *) set : sigsetT ): BOOLEAN;
  87. (**)
  88. VAR __REG__ idx : SigsetRange;
  89.     __REG__ tmp : WORDSET;
  90.  
  91. BEGIN
  92.  idx := 0;
  93.  tmp := set[MAXSIGSET];
  94.  set[MAXSIGSET] := WORDSET{0..15};
  95.  WHILE set[idx] = WORDSET{} DO
  96.    INC(idx);
  97.  END;
  98.  
  99.  IF idx = MAXSIGSET THEN
  100.    RETURN(tmp = WORDSET{});
  101.  ELSE
  102.    RETURN(FALSE);
  103.  END;
  104. END SigsetIsEmpty;
  105.  
  106. (*---------------------------------------------------------------------------*)
  107.  
  108. PROCEDURE SigsetDiff ((* EIN/ -- *)     from : sigsetT;
  109.                       (* EIN/ -- *)     sub  : sigsetT;
  110.                       (* -- /AUS *) VAR res  : sigsetT );
  111. (**)
  112. VAR __REG__ idx : SigsetRange;
  113.  
  114. BEGIN
  115.  FOR idx := 0 TO MAXSIGSET DO
  116.    res[idx] := from[idx] - sub[idx];
  117.  END;
  118. END SigsetDiff;
  119.  
  120. (*---------------------------------------------------------------------------*)
  121.  
  122. PROCEDURE SigsetUnion ((* EIN/ -- *)     set1 : sigsetT;
  123.                        (* EIN/ -- *)     set2 : sigsetT;
  124.                        (* -- /AUS *) VAR res  : sigsetT );
  125. (**)
  126. VAR __REG__ idx : SigsetRange;
  127.  
  128. BEGIN
  129.  FOR idx := 0 TO MAXSIGSET DO
  130.    res[idx] := set1[idx] + set2[idx];
  131.  END;
  132. END SigsetUnion;
  133.  
  134. (*---------------------------------------------------------------------------*)
  135.  
  136. PROCEDURE SigsetIsMember ((* EIN/ -- *)     sig : Signal;
  137.                           (* EIN/ -- *) VAR set : sigsetT ): BOOLEAN;
  138. (**)
  139. BEGIN
  140.  RETURN(       VAL(WORDSETRANGE,VAL(CARDINAL,sig) MOD 16)
  141.         IN set[VAL(WORDSETRANGE,VAL(CARDINAL,sig) DIV 16)]);
  142. END SigsetIsMember;
  143.  
  144. (*---------------------------------------------------------------------------*)
  145.  
  146. PROCEDURE SigsetInclude ((* EIN/ -- *)     sig : Signal;
  147.                          (* EIN/AUS *) VAR set : sigsetT );
  148. (**)
  149. BEGIN
  150.  INCL(set[VAL(WORDSETRANGE,VAL(CARDINAL,sig) DIV 16)],
  151.           VAL(WORDSETRANGE,VAL(CARDINAL,sig) MOD 16) );
  152. END SigsetInclude;
  153.  
  154. (*---------------------------------------------------------------------------*)
  155.  
  156. PROCEDURE SigsetExclude ((* EIN/ -- *)     sig : Signal;
  157.                          (* EIN/AUS *) VAR set : sigsetT );
  158. (**)
  159. BEGIN
  160.  EXCL(set[VAL(WORDSETRANGE,VAL(CARDINAL,sig) DIV 16)],
  161.           VAL(WORDSETRANGE,VAL(CARDINAL,sig) MOD 16) );
  162. END SigsetExclude;
  163.  
  164. (*---------------------------------------------------------------------------*)
  165.  
  166. PROCEDURE sigemptyset ((* -- /AUS *) VAR set : sigsetT );
  167. (**)
  168. VAR __REG__ idx : SigsetRange;
  169.  
  170. BEGIN
  171.  FOR idx := 0 TO MAXSIGSET DO
  172.    set[idx] := WORDSET{};
  173.  END;
  174. END sigemptyset;
  175.  
  176. (*---------------------------------------------------------------------------*)
  177.  
  178. PROCEDURE sigfillset ((* -- /AUS *) VAR set : sigsetT );
  179. (**)
  180. VAR __REG__ idx : SigsetRange;
  181.  
  182. BEGIN
  183.  FOR idx := 0 TO MAXSIGSET DO
  184.    set[idx] := WORDSET{0..15};
  185.  END;
  186. END sigfillset;
  187.  
  188. (*---------------------------------------------------------------------------*)
  189.  
  190. PROCEDURE sigaddset ((* EIN/AUS *) VAR set : sigsetT;
  191.                      (* EIN/ -- *)     sig : Signal  ): INTEGER;
  192. (**)
  193. BEGIN
  194.  IF ORD(sig) > ORD(MAXSIG) THEN
  195.    e.errno := e.EINVAL;
  196.    RETURN(-1);
  197.  END;
  198.  SigsetInclude(sig, set);
  199.  RETURN(0);
  200. END sigaddset;
  201.  
  202. (*---------------------------------------------------------------------------*)
  203.  
  204. PROCEDURE sigdelset ((* EIN/AUS *) VAR set : sigsetT;
  205.                      (* EIN/ -- *)     sig : Signal  ): INTEGER;
  206. (**)
  207. BEGIN
  208.  IF ORD(sig) > ORD(MAXSIG) THEN
  209.    e.errno := e.EINVAL;
  210.    RETURN(-1);
  211.  END;
  212.  SigsetExclude(sig, set);
  213.  RETURN(0);
  214. END sigdelset;
  215.  
  216. (*---------------------------------------------------------------------------*)
  217.  
  218. PROCEDURE sigismember ((* EIN/ -- *) set : sigsetT;
  219.                        (* EIN/ -- *) sig : Signal  ): INTEGER;
  220. (**)
  221. BEGIN
  222.  IF ORD(sig) > ORD(MAXSIG) THEN
  223.    e.errno := e.EINVAL;
  224.    RETURN(-1);
  225.  END;
  226.  IF SigsetIsMember(sig, set) THEN
  227.    RETURN(1);
  228.  ELSE
  229.    RETURN(0);
  230.  END;
  231. END sigismember;
  232.  
  233. (*---------------------------------------------------------------------------*)
  234. #if (defined HM2)
  235. (*$E+*)
  236. #endif
  237. PROCEDURE dispatch ((* EIN/ -- *) sig : UNSIGNEDWORD );
  238. BEGIN
  239.  Handler[VAL(Signal,sig)].proc(VAL(Signal,sig));
  240. END dispatch;
  241. #if (defined HM2)
  242. (*$E=*)
  243. #endif
  244. (*---------------------------------------------------------------------------*)
  245.  
  246. PROCEDURE sigaction ((* EIN/ -- *) sig  : Signal;
  247.                      (* EIN/ -- *) act  : SigactionPtr;
  248.                      (* EIN/ -- *) oact : SigactionPtr ): INTEGER;
  249. (**)
  250. VAR
  251. BEGIN
  252.  IF ORD(sig) > ORD(MAXSIG) THEN
  253.    e.errno := e.EINVAL;
  254.    RETURN(-1);
  255.  END;
  256.  e.errno := e.ENOSYS;
  257.  RETURN(-1);
  258. END sigaction;
  259.  
  260. (*---------------------------------------------------------------------------*)
  261.  
  262. PROCEDURE kill ((* EIN/ -- *) pid : pidT;
  263.                 (* EIN/ -- *) sig : Signal ): INTEGER;
  264. (**)
  265. VAR handler : SignalHandler;
  266.     dummy   : INTEGER;
  267.     res     : INTEGER;
  268.  
  269. BEGIN
  270.  IF ORD(sig) > ORD(MAXSIG) THEN
  271.    e.errno := e.EINVAL;
  272.    RETURN(-1);
  273.  END;
  274.  IF MiNT THEN
  275.    IF Pkill(pid, ORD(sig), res) THEN
  276.      RETURN(0);
  277.    ELSE
  278.      e.errno := res;
  279.      RETURN(-1);
  280.    END
  281.  ELSE
  282.    IF (pid < 0) OR (pid > 0) AND (pid <> DosPid(BASEP)) THEN
  283.      e.errno := e.ESRCH;
  284.      RETURN(-1);
  285.    END;
  286.    handler := Handler[sig];
  287.    IF (sig = SIGNULL) OR (handler.long = SigIgn) THEN
  288.      RETURN(0);
  289.    ELSIF (sig <> SIGKILL)
  290.      AND (sig <> SIGSTOP)
  291.      AND SigsetIsMember(sig, SIGMASK.sigset)
  292.    THEN
  293.      SigsetInclude(sig, SIGPENDING.sigset);
  294.    ELSE
  295.      SigsetExclude(sig, SIGPENDING.sigset);
  296.      IF handler.long = SigDfl THEN
  297.        IF (sig = SIGCONT) OR (sig = SIGCHLD) THEN
  298.          RETURN(0);
  299.        ELSE
  300.          Pterm(VAL(CARDINAL,sig) * 256); (* Signal in obere 8 Bit *)
  301.        END;
  302.      ELSE
  303.        handler.proc(sig);
  304.      END;
  305.    END;
  306.  END;
  307. END kill;
  308.  
  309. (*---------------------------------------------------------------------------*)
  310.  
  311. PROCEDURE DeliverUnblocked;
  312. (**)
  313. VAR         unblocked : sigsetT;
  314.     __REG__ sig       : Signal;
  315.     __REG__ void      : INTEGER;
  316.  
  317. BEGIN
  318.  SigsetDiff(SIGPENDING.sigset, SIGMASK.sigset, unblocked);
  319.  IF NOT SigsetIsEmpty(unblocked) THEN
  320.    FOR sig := MINSIG TO MAXSIG DO
  321.      IF SigsetIsMember(sig, unblocked) THEN
  322.        void := kill(0, sig);
  323.      END;
  324.    END;
  325.  END;
  326. END DeliverUnblocked;
  327.  
  328. (*---------------------------------------------------------------------------*)
  329.  
  330. PROCEDURE sigprocmask ((* EIN/ -- *) how  : BlockType;
  331.                        (* EIN/ -- *) set  : SigsetPtr;
  332.                        (* EIN/ -- *) oset : SigsetPtr ): INTEGER;
  333. (**)
  334. VAR old     : UNSIGNEDLONG;
  335.     mintsig : MiNTSigset;
  336.  
  337. BEGIN
  338.  CASE how OF
  339.    SigBlock:
  340.      IF MiNT THEN
  341.        WITH mintsig DO
  342.          IF set = NULL THEN
  343.            siglong := 0;
  344.          ELSE
  345.            sigset  := set^;
  346.          END;
  347.          siglong := Psigblock(siglong);
  348.          IF oset <> NULL THEN
  349.            oset^ := sigset;
  350.          END;
  351.        END;
  352.      ELSE
  353.        WITH SIGMASK DO
  354.          IF oset <> NULL THEN
  355.            oset^ := sigset;
  356.          END;
  357.          IF set <> NULL THEN
  358.            SigsetUnion(sigset, set^, sigset);
  359.          END;
  360.        END;
  361.      END;
  362.   |SigUnBlock:
  363.      IF MiNT THEN
  364.        WITH mintsig DO
  365.          siglong := Psigblock(0);
  366.          IF oset <> NULL THEN
  367.            oset^ := sigset;
  368.          END;
  369.          IF set <> NULL THEN
  370.            SigsetDiff(sigset, set^, sigset);
  371.            old := Psigsetmask(siglong);
  372.          END;
  373.        END;
  374.      ELSE
  375.        WITH SIGMASK DO
  376.          IF oset <> NULL THEN
  377.            oset^ := sigset;
  378.          END;
  379.          IF set <> NULL THEN
  380.            SigsetDiff(sigset, set^, sigset);
  381.            DeliverUnblocked;
  382.          END;
  383.        END;
  384.      END;
  385.   ELSE (* SigSetMask *)
  386.     IF MiNT THEN
  387.       WITH mintsig DO
  388.         IF set = NULL THEN
  389.           siglong := Psigblock(0);
  390.         ELSE
  391.           sigset  := set^;
  392.           siglong := Psigsetmask(siglong);
  393.         END;
  394.         IF oset <> NULL THEN
  395.           oset^ := sigset;
  396.         END;
  397.       END;
  398.     ELSE
  399.       WITH SIGMASK DO
  400.         IF oset <> NULL THEN
  401.           oset^ := sigset;
  402.         END;
  403.         IF set <> NULL THEN
  404.           sigset := set^;
  405.           DeliverUnblocked;
  406.         END;
  407.       END;
  408.     END;
  409.  END;
  410.  RETURN(0);
  411. END sigprocmask;
  412.  
  413. (*---------------------------------------------------------------------------*)
  414.  
  415. PROCEDURE sigpending ((* -- /AUS *) VAR set : sigsetT ): INTEGER;
  416. (**)
  417. VAR sigs : MiNTSigset;
  418.  
  419. BEGIN
  420.  IF MiNT THEN
  421.    WITH sigs DO
  422.      siglong := Psigpending();
  423.      set     := sigset;
  424.    END;
  425.  ELSE;
  426.    set := SIGPENDING.sigset;
  427.  END;
  428.  RETURN(0);
  429. END sigpending;
  430.  
  431. (*---------------------------------------------------------------------------*)
  432.  
  433. PROCEDURE pause ( ): INTEGER;
  434. (**)
  435. BEGIN
  436.  IF MiNT THEN
  437.    Pause;
  438.  END;
  439.  e.errno := e.EINTR;
  440.  RETURN(-1);
  441. END pause;
  442.  
  443. (*---------------------------------------------------------------------------*)
  444.  
  445. PROCEDURE sigsuspend ((* EIN/ -- *) sigmask : sigsetT ): INTEGER;
  446. (**)
  447. VAR         mask : MiNTSigset;
  448.     __REG__ old  : UNSIGNEDLONG;
  449.  
  450. BEGIN
  451.  mask.sigset := sigmask;
  452.  IF MiNT THEN
  453.    Psigpause(mask.siglong);
  454.  ELSE
  455.    WITH SIGMASK DO
  456.      old     := siglong;
  457.      SIGMASK := mask;
  458.      DeliverUnblocked;
  459.      siglong := old;
  460.    END;
  461.  END;
  462.  e.errno := e.EINTR;
  463.  RETURN(-1);
  464. END sigsuspend;
  465.  
  466. (*---------------------------------------------------------------------------*)
  467.  
  468. PROCEDURE sleep ((* EIN/ -- *) seconds : CARDINAL ): CARDINAL;
  469. (**)
  470. VAR __REG__ until : UNSIGNEDLONG;
  471.     __REG__ void  : BOOLEAN;
  472.             res   : INTEGER;
  473.  
  474. BEGIN
  475.  IF MiNT THEN
  476.    (* Ab MiNT 1.08 ist 'Fselect' durch Interrupt unterbrechbar *)
  477.    WHILE seconds > 32 DO
  478.      void := Fselect(32000, NULL, NULL, NULL, res);
  479.      DEC(seconds, 32);
  480.    END;
  481.    void := Fselect(1000 * seconds, NULL, NULL, NULL, res);
  482.  ELSE
  483.    until := VAL(UNSIGNEDLONG,seconds);
  484.    INC(until, until);
  485.    INC(until, until);
  486.    INC(until, VAL(UNSIGNEDLONG,seconds));
  487.    INC(until, SysClock());
  488.    REPEAT
  489.    UNTIL SysClock() >= until;
  490.  END;
  491.  RETURN(0);
  492. END sleep;
  493.  
  494. (*---------------------------------------------------------------------------*)
  495.  
  496. PROCEDURE alarm ((* EIN/ -- *) sec : CARDINAL ): CARDINAL;
  497. (**)
  498. CONST MAXSEC = LIC(2147483);
  499.  
  500. VAR __REG__ time : SIGNEDLONG;
  501.  
  502. BEGIN
  503.  IF MiNT THEN
  504.    time := VAL(SIGNEDLONG,sec);
  505.    IF time > MAXSEC THEN
  506.      (* sonst gibts Ueberlauf in MiNT *)
  507.      time := MAXSEC;
  508.    END;
  509.    RETURN(VAL(CARDINAL,Talarm(time)));
  510.  END;
  511.  RETURN(0);
  512. END alarm;
  513.  
  514. (*===========================================================================*)
  515.  
  516. VAR signal : Signal;
  517.  
  518. BEGIN (* sig *)
  519.  MiNT := MiNTVersion() > 0;
  520. #if 0
  521.  WITH Wrapper DO
  522. #ifdef MM2
  523. (* ???? *)
  524. #else
  525.    code1[0] := 202F0004H; (* move.l  4(SP),D0 *)
  526.    code1[1] := 4E560000H; (* link    A6,#0 *)
  527.    code1[2] := 3F004EB9H; (* move.w  D0,-(SP)  &  jsr ... *)
  528.    call     := dispatch;  (* ... dispatch *)
  529.    code2    := 4E5E4E75H; (* unlk    A6  &  rts *)
  530. #endif
  531.  END;
  532. #endif
  533.  SIGMASK.siglong    := 0H;
  534.  SIGPENDING.siglong := 0H;
  535.  
  536.  FOR signal := MINSIG TO MAXSIG DO
  537.    Handler[signal].long := SigDfl;
  538.  END;
  539.  Handler[SIGNULL].long := SigIgn;
  540.  Handler[SIGCHLD].long := SigIgn;
  541. END sig.
  542.